package org.wesc.boot.service.websocket;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * WebSocket服务
 *
 * @author Wesley
 */
@Slf4j
@Data
@EqualsAndHashCode
@ServerEndpoint("/websocket/{userId}")
@Component
public class WebSocket {

    private Session session;

    private String userId;

    /**
     * 记录当前在线的Session
     */
    public static final CopyOnWriteArraySet<WebSocket> ONLINE_SESSION_SET = new CopyOnWriteArraySet<>();

    /**
     * 新增连接
     */
    @OnOpen
    public void onOpen(@PathParam(value = "userId") String userId, Session session) {
        this.userId = userId;
        this.session = session;
        ONLINE_SESSION_SET.add(this);
        log.info("WebSocket有新的连接，总数为:" + ONLINE_SESSION_SET.size());
    }

    /**
     * 关闭连接
     */
    @OnClose
    public void onClose() {
        ONLINE_SESSION_SET.remove(this);
        log.info("WebSocket连接断开，总数为:" + ONLINE_SESSION_SET.size());
    }

    /**
     * 接收消息
     */
    @OnMessage
    public void onMessage(@PathParam(value = "userId") String userId, String message) {
        log.debug("WebSocket收到客户端: {}, 消息: {}", userId, message);
        // 广播消息
        sendMessage(message);
    }

    /**
     * 异常处理
     */
    @OnError
    public void onError(Session session, Throwable throwable) {
        try {
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        throwable.printStackTrace();
    }

    /**
     * 发送消息
     */
    public void sendMessage(Session session, String message) {
        if (null == session) {
            return;
        }
        session.getAsyncRemote().sendText(message);
    }

    /**
     * 给单个用户推送消息
     */
    public void sendMessage(String userId, String message) {
        ONLINE_SESSION_SET.forEach((obj) -> {
            if (obj.getUserId().equals(userId)) {
                sendMessage(obj.getSession(), message);
            }
        });
    }

    /**
     * 给用户列表推送消息
     */
    public void sendMessage(List<String> userIdList, String message) {
        ONLINE_SESSION_SET.forEach((obj) -> {
            if (userIdList.contains(obj.getUserId())) {
                sendMessage(obj.getSession(), message);
            }
        });
    }

    /**
     * 给多个用户推送消息
     */
    public void sendMessage(String[] userIds, String message) {
        List<String> userIdList = Arrays.asList(userIds);
        sendMessage(userIdList, message);
    }

    /**
     * 向所有在线人发送消息
     */
    public void sendMessage(String message) {
        ONLINE_SESSION_SET.forEach((obj) -> sendMessage(obj.getSession(), message));
    }

}